package org.hackystat.projectbrowser.page.setaction;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.hackystat.ambientdevice.server.jaxb.Action;

/**
 * The SetActionForm is in charge of gathering information for adding/editing an action of the
 * trigger action pair.
 * 
 * @author Sonwright M. Gomez
 * 
 */
public class SetActionForm extends Form {

  /** Support serialization. */
  private static final long serialVersionUID = 1L;
  /** Action Model */
  private final ActionModel actionModel;
  /** The page parameters */
  private final PageParameters param;
  /** The selected Action Type */
  private String selectedActionType = "";
  /** The selected Device Name */
  private String selectedDeviceName = "";
  /** The Selected Trigger Value */
  private String selectedActionValue = "";
  /** The map containing the values for an action. */
  @SuppressWarnings("unchecked")
  private Map<String, ArrayList<String>> valueMap = new HashMap<String, ArrayList<String>>();
  /** The map containing the action types for an action. */
  @SuppressWarnings("unchecked")
  private Map<String, ArrayList<String>> actionTypeMap = new HashMap<String, ArrayList<String>>();
  /** The string constants, for better performance. */
  private static final String DEVICE_NAME_TOKEN = "deviceName";
  private static final String ACTION_TYPE_TOKEN = "actionType";
  private static final String VALUE_TOKEN = "valueModel";

  /**
   * SetActionForm creates the form for adding or editing an action.
   * 
   * @param id The id containing the wicket id.
   * @param model the model.
   * @param param the parameters that may be passed.
   */
  public SetActionForm(String id, ActionModel model, PageParameters param) {
    super(id);
    this.actionModel = model;
    this.param = param;

    valueMap.put("ChangeColor", ActionModel.getChoices("ChangeColor"));
    valueMap.put("ChangeAnimation", ActionModel.getChoices("ChangeAnimation"));
    valueMap.put("ChangeEarPos", ActionModel.getChoices("ChangeEarPos"));
    valueMap.put("MoveLeftEarPosition", ActionModel.getChoices("MoveLeftEarPosition"));
    valueMap.put("MoveRightEarPosition", ActionModel.getChoices("MoveRightEarPosition"));
    valueMap.put("TTS", ActionModel.getChoices("TTS"));

    // Right now, I have it so that you can only have ONE orb or ONE bunny as your devices.
    // I hope to change this later once the system is actually functional. What will happen
    // is that the user may customize the names of their devices, and that will show up
    // in the deviceName drop down menu.
    actionTypeMap.put("Orb", ActionModel.getChoices("Orb"));
    actionTypeMap.put("Bunny", ActionModel.getChoices("Bunny"));
       
    IModel actionTypeModel = new AbstractReadOnlyModel() {
      /**
       * For Serialization
       */
      private static final long serialVersionUID = 1L;

      public Object getObject() {
        if ((List<String>) actionTypeMap.get(selectedDeviceName) == null) {
          return Collections.emptyList();
        }
        else {
          return (List<String>) actionTypeMap.get(selectedDeviceName);
        }
      }
    };

    //Creates the model for the value
    IModel valueModel = new AbstractReadOnlyModel() {
      /**
       * For Serialization
       */
      private static final long serialVersionUID = 1L;

      //This will populate the menu according to what has been selected in selection Action Type
      public Object getObject() {
        if ((List<String>) valueMap.get(selectedActionType) == null) {
          return Collections.emptyList();
        }
        else {
          return (List<String>) valueMap.get(selectedActionType);
        }
      }
    };

    //Create the drop down menus
    final DropDownChoice deviceNameChoices = new DropDownChoice(
                                  "deviceName",
                                  new PropertyModel(this, "selectedDeviceName"), 
                                  new Model(ActionModel.getChoices("deviceName")));
    final DropDownChoice actionTypeChoices = new DropDownChoice(
                                  "actionType", 
                                  new PropertyModel(this, "selectedActionType"), 
                                  actionTypeModel);
    final DropDownChoice valueChoices = new DropDownChoice(
                                  "valueModel", 
                                  new PropertyModel(this, "selectedActionValue"), 
                                  valueModel);
    
   valueChoices.setOutputMarkupId(true);
    actionTypeChoices.setOutputMarkupId(true);

    //Add to the form
    add(deviceNameChoices);
    add(actionTypeChoices);
    add(valueChoices);

    //Changes the form after changes are detected
    deviceNameChoices.add(new AjaxFormComponentUpdatingBehavior("onchange") {

      /**
       * For Serialization
       */
      private static final long serialVersionUID = 1L;

      @Override
      protected void onUpdate(AjaxRequestTarget arg0) {
        arg0.addComponent(actionTypeChoices);

      }

    });

    actionTypeChoices.add(new AjaxFormComponentUpdatingBehavior("onchange") {

      /**
       * 
       */
      private static final long serialVersionUID = 1L;

      @Override
      protected void onUpdate(AjaxRequestTarget target) {
        target.addComponent(valueChoices);
      }
    });
  }

  /**
   * Gets the info needed to create/edit a action
   */
  @Override
  protected void onSubmit() {
    actionModel.setActionDeviceName(selectedDeviceName);
    actionModel.setActionActionType(selectedActionType);
    actionModel.setActionValue(selectedActionValue);
    System.out.println("VALUE: " + selectedActionValue);
    param.put(DEVICE_NAME_TOKEN, actionModel.getActionDeviceName());
    param.put(ACTION_TYPE_TOKEN, actionModel.getActionActionType());
    param.put(VALUE_TOKEN, actionModel.getActionValue());
    Action action = new Action();
    action.setDeviceName(selectedDeviceName);
    action.setActionType(selectedActionType);
    action.setValue(selectedActionValue);
  }

}
